using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
using Konst3d.Efficiency.IO;

namespace Konst3d.Efficiency.Suite.SparsedBinary
{
    internal class MonitoringGroupStorage : IMonitoringGroupStorage, IDisposable
    {
        #region Constants

        private const string GROUP_FILE_EXT = ".group";
        private const string MONITORS_FILE_EXT = ".monitors";
        private const string TASKS_FILE_EXT = ".tasks";

        #endregion // Constants

        #region Create/Open/Delete Methods

        public static MonitoringGroupStorage Create(string path, bool overwrite, ICryptographicEngine cryptographicEngine, int id, string title, string description, DateTime created)
        {
            Contract.Requires(!String.IsNullOrEmpty(path));
            Contract.Requires(cryptographicEngine != null);

            MonitoringGroupFile groupFile = null;
            ListFile<int> monitorsFile = null;
            ListFile<int> tasksFile = null;
            LabelsStorage labels = null;

            try
            {
                labels = LabelsStorage.Create(path, overwrite, cryptographicEngine);
                groupFile = MonitoringGroupFile.Create(path + GROUP_FILE_EXT, overwrite, cryptographicEngine, created, labels.AddLabel(title), labels.AddLabel(description), id);
                monitorsFile = ListFile<int>.Create(new ListFileLayoutInt(), false, path + MONITORS_FILE_EXT, overwrite);
                tasksFile = ListFile<int>.Create(new ListFileLayoutInt(), false, path + TASKS_FILE_EXT, overwrite);

                return new MonitoringGroupStorage(groupFile, monitorsFile, tasksFile, labels);
            }
            catch
            {
                if (groupFile != null)
                {
                    groupFile.Dispose();
                }

                if (monitorsFile != null)
                {
                    monitorsFile.Dispose();
                }

                if (tasksFile != null)
                {
                    tasksFile.Dispose();
                }

                if (labels != null)
                {
                    labels.Dispose();
                }

                throw;
            }
        }

        public static MonitoringGroupStorage Open(string path, ICryptographicEngine cryptographicEngine)
        {
            Contract.Requires(!String.IsNullOrEmpty(path));
            Contract.Requires(cryptographicEngine != null);

            MonitoringGroupFile groupFile = null;
            ListFile<int> monitorsFile = null;
            ListFile<int> tasksFile = null;
            LabelsStorage labels = null;

            try
            {
                groupFile = MonitoringGroupFile.Open(path + GROUP_FILE_EXT, cryptographicEngine);
                monitorsFile = ListFile<int>.Open(new ListFileLayoutInt(), false, path + MONITORS_FILE_EXT);
                tasksFile = ListFile<int>.Open(new ListFileLayoutInt(), false, path + TASKS_FILE_EXT);
                labels = LabelsStorage.Open(path, cryptographicEngine);

                return new MonitoringGroupStorage(groupFile, monitorsFile, tasksFile, labels);
            }
            catch
            {
                if (groupFile != null)
                {
                    groupFile.Dispose();
                }

                if (monitorsFile != null)
                {
                    monitorsFile.Dispose();
                }

                if (tasksFile != null)
                {
                    tasksFile.Dispose();
                }

                if (labels != null)
                {
                    labels.Dispose();
                }

                throw;
            }
        }

        public void Delete()
        {
            Contract.Requires(!_disposed);

            _groupFile.Delete();
            _monitorsFile.Delete();
            _tasksFile.Delete();
            _labels.Delete();

            Dispose();
        }

        #endregion // Create/Open/Delete Methods

        #region Constructor/Finalizer

        private MonitoringGroupStorage(MonitoringGroupFile groupFile, ListFile<int> monitorsFile, ListFile<int> tasksFile, LabelsStorage labels)
        {
            Contract.Requires(groupFile != null);
            Contract.Requires(monitorsFile != null);
            Contract.Requires(tasksFile != null);
            Contract.Requires(labels != null);

            _groupFile = groupFile;
            _monitorsFile = monitorsFile;
            _tasksFile = tasksFile;
            _labels = labels;

            _title = _labels.GetLabel(_groupFile.TitleID);
            _description = _labels.GetLabel(_groupFile.DescrID);
        }

        ~MonitoringGroupStorage()
        {
            Dispose(false);
        }

        #endregion // Constructor/Finalizer

        #region IMonitoringGroupStorage Members

        public int ID
        {
            get
            {
                return _groupFile.ID;
            }
            set
            {
                _groupFile.ID = value;
            }
        }

        public string Title
        {
            get
            {
                return _title;
            }
            set
            {
                _groupFile.TitleID = _labels.UpdateLabel(_groupFile.TitleID, value);
                _title = value;
            }
        }

        public string Description
        {
            get
            {
                return _description;
            }
            set
            {
                _groupFile.DescrID = _labels.UpdateLabel(_groupFile.DescrID, value);
                _description = value;
            }
        }

        public DateTime Created
        {
            get
            {
                return _groupFile.Created;
            }
            set
            {
                _groupFile.Created = value;
            }
        }

        public ICollection<int> Monitors
        {
            get
            {
                return _monitorsFile;
            }
        }

        public ICollection<int> Tasks
        {
            get
            {
                return _tasksFile;
            }
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            GC.SuppressFinalize(this);
            Dispose(true);
        }

        private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _groupFile.Dispose();
                    _groupFile = null;

                    _monitorsFile.Dispose();
                    _monitorsFile = null;

                    _tasksFile.Dispose();
                    _tasksFile = null;

                    _labels.Dispose();
                    _labels = null;
                }

                _disposed = true;
            }
        }

        #endregion

        #region Fields

        private bool _disposed;
        private MonitoringGroupFile _groupFile;
        private LabelsStorage _labels;
        private ListFile<int> _monitorsFile;
        private ListFile<int> _tasksFile;
        private string _title;
        private string _description;

        #endregion // Fields
    }
}
